package com.mm.cloud.common.redis.service.impl;

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.mm.cloud.common.redis.service.IRedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * Redis操作公共服务实现
 *
 * @author mr
 * @since 2021-06-09
 */
@Slf4j
@Component
public class RedisServiceImpl<K, V> implements IRedisService<K, V> {

    private RedisTemplate<K, V> redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        //key采用string序列化方式
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        //value采用fastjson序列化方式
        RedisSerializer<Object> fastJson2JsonSerializer = new FastJsonRedisSerializer<>(Object.class);
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(fastJson2JsonSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(fastJson2JsonSerializer);
        this.redisTemplate = redisTemplate;
    }

    @Override
    public Boolean set(K k, V v) {
        try {
            redisTemplate.opsForValue().set(k, v);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    @Override
    public Boolean set(K k, V v, long seconds, TimeUnit unit) {
        try {
            redisTemplate.opsForValue().set(k, v, seconds, unit);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    @Override
    public V get(K k) {
        return redisTemplate.opsForValue().get(k);
    }

    @Override
    public Boolean delete(K k) {
        return redisTemplate.delete(k);
    }

    @Override
    public Long getExpire(K k) {
        return redisTemplate.getExpire(k);
    }

    @Override
    public Boolean expire(K k, long seconds, TimeUnit unit) {
        return redisTemplate.expire(k, seconds, unit);
    }

    @Override
    public V getAndSet(K k, V v, long seconds, TimeUnit unit) {
        V result = redisTemplate.opsForValue().getAndSet(k, v);
        Long oldTime = this.getExpire(k);
        if (null == oldTime || oldTime <= seconds / 2) {
            this.expire(k, seconds, unit);
        }
        return result;
    }

    @Override
    public Long inc(K key, long length) {
        return redisTemplate.opsForValue().increment(key, length);
    }

    @Override
    public Boolean exists(K key) {
        return redisTemplate.hasKey(key);
    }
}
